"""
动态模型发现API - 基于配置的API密钥自动检测可用模型
"""
from fastapi import APIRouter, Depends, HTTPException, Query
from typing import List, Dict, Any, Optional
from datetime import datetime, timedelta
import asyncio
import httpx
from pydantic import BaseModel, Field
import logging

from ..core.auth import get_current_user
from ..core.config import settings
from ..models.config_manager import ConfigManager
from ..models.health_checker import ModelHealthChecker

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/api/v1/models", tags=["model-discovery"])

# 重用model_config中的测试函数
from .model_config import test_model_connection as config_test_model_connection

# 响应模型
class ModelCapabilities(BaseModel):
    max_tokens: int = Field(default=4096)
    supports_streaming: bool = Field(default=True)
    supports_function_calling: bool = Field(default=False)
    supports_vision: bool = Field(default=False)
    context_window: int = Field(default=4096)
    
class AvailableModel(BaseModel):
    id: str
    name: str
    display_name: str
    provider: str
    provider_name: str
    base_url: str
    status: str = Field(default="unknown")  # available, unavailable, checking
    capabilities: ModelCapabilities
    last_checked: Optional[datetime] = None
    response_time: Optional[int] = None  # 毫秒
    error_message: Optional[str] = None
    version: Optional[str] = None
    recommended: bool = Field(default=False)

class ModelDiscoveryResponse(BaseModel):
    models: List[AvailableModel]
    last_refresh: datetime
    cache_ttl: int = Field(default=900)  # 15分钟缓存

# 模型发现服务
class ModelDiscoveryService:
    def __init__(self):
        self.config_manager = ConfigManager()
        self.health_checker = ModelHealthChecker()
        self._cache: Dict[str, Any] = {}
        self._cache_expiry: Optional[datetime] = None
        
    async def discover_openai_models(self, base_url: str, api_key: str) -> List[Dict]:
        """发现OpenAI兼容API的模型"""
        try:
            async with httpx.AsyncClient() as client:
                response = await client.get(
                    f"{base_url}/models",
                    headers={"Authorization": f"Bearer {api_key}"},
                    timeout=10.0
                )
                if response.status_code == 200:
                    data = response.json()
                    return data.get("data", [])
        except Exception as e:
            logger.error(f"Failed to discover OpenAI models: {e}")
        return []
    
    async def discover_anthropic_models(self, base_url: str, api_key: str) -> List[Dict]:
        """发现Anthropic Claude模型"""
        # Claude API不提供模型列表端点，返回已知模型
        known_models = [
            {"id": "claude-3-opus-20240229", "name": "Claude 3 Opus"},
            {"id": "claude-3-sonnet-20240229", "name": "Claude 3 Sonnet"},
            {"id": "claude-3-haiku-20240307", "name": "Claude 3 Haiku"},
            {"id": "claude-4.1", "name": "Claude 4.1"},
            {"id": "claude-opus-4.1", "name": "Claude Opus 4.1"},
        ]
        return known_models
    
    async def discover_deepseek_models(self, base_url: str, api_key: str) -> List[Dict]:
        """发现DeepSeek模型"""
        try:
            # DeepSeek使用OpenAI兼容API
            async with httpx.AsyncClient() as client:
                response = await client.get(
                    f"{base_url}/models",
                    headers={"Authorization": f"Bearer {api_key}"},
                    timeout=10.0
                )
                if response.status_code == 200:
                    data = response.json()
                    models_data = data.get("data", [])
                    
                    # 处理DeepSeek模型数据，确保格式正确
                    processed_models = []
                    for model in models_data:
                        model_id = model.get("id", "")
                        processed_models.append({
                            "id": model_id,
                            "name": model.get("name", model_id),
                            "object": model.get("object", "model"),
                            "created": model.get("created"),
                            "owned_by": model.get("owned_by", "deepseek"),
                            "max_tokens": 4096,  # DeepSeek默认支持的最大tokens
                            "context_length": 32768  # DeepSeek的上下文长度
                        })
                    
                    logger.info(f"Successfully discovered {len(processed_models)} DeepSeek models: {[m['id'] for m in processed_models]}")
                    return processed_models
                else:
                    raise Exception(f"DeepSeek API returned status {response.status_code}: {response.text}")
                    
        except Exception as e:
            logger.error(f"Failed to discover DeepSeek models: {e}")
            raise Exception(f"Unable to fetch DeepSeek models: {str(e)}")
    
    async def get_available_models(self, force_refresh: bool = False, user_id: str = None) -> List[AvailableModel]:
        """获取所有可用模型"""
        # 检查缓存
        cache_key = f"models_{user_id}" if user_id else "models_global"
        if not force_refresh and self._cache_expiry and datetime.now() < self._cache_expiry:
            if cache_key in self._cache:
                return self._cache[cache_key]
        
        available_models = []
        
        # 从数据库获取用户配置的模型
        from ..core.database import get_db
        db = await get_db()
        
        # 查询用户配置的模型
        query = {"enabled": True}
        if user_id:
            query["user_id"] = user_id
        
        cursor = db.model_configs.find(query)
        user_configs = await cursor.to_list(length=100)
        
        # 并发检测所有配置的模型
        tasks = []
        for config in user_configs:
            if config.get("enabled", True):
                tasks.append(self._check_model_availability(config))
        
        if tasks:
            results = await asyncio.gather(*tasks, return_exceptions=True)
            for result in results:
                if isinstance(result, AvailableModel):
                    available_models.append(result)
                elif isinstance(result, list):
                    available_models.extend(result)
        
        # 更新缓存
        self._cache[cache_key] = available_models
        self._cache_expiry = datetime.now() + timedelta(minutes=15)
        
        return available_models
    
    async def _check_model_availability(self, config: Dict) -> List[AvailableModel]:
        """检查单个配置的模型可用性"""
        models = []
        provider = config.get("provider", "").lower()
        base_url = config.get("base_url", "")
        api_key = config.get("api_key", "")
        
        # 基于提供商发现模型
        discovered_models = []
        if provider == "openai":
            discovered_models = await self.discover_openai_models(base_url, api_key)
        elif provider in ["anthropic", "claude"]:
            discovered_models = await self.discover_anthropic_models(base_url, api_key)
        elif provider == "deepseek":
            discovered_models = await self.discover_deepseek_models(base_url, api_key)
        
        # 转换为AvailableModel
        for model_data in discovered_models:
            model_id = model_data.get("id", "")
            model_name = model_data.get("name", model_id)
            
            # 检测模型健康状态
            health_status = await self.health_checker.check_model_health(
                base_url, api_key, model_id, provider
            )
            
            model = AvailableModel(
                id=f"{provider}_{model_id}",
                name=model_id,
                display_name=model_name,
                provider=provider,
                provider_name=config.get("provider_name", provider.title()),
                base_url=base_url,
                status=health_status.get("status", "unknown"),
                capabilities=ModelCapabilities(
                    max_tokens=model_data.get("max_tokens", 4096),
                    context_window=model_data.get("context_length", 4096)
                ),
                last_checked=datetime.now(),
                response_time=health_status.get("response_time"),
                error_message=health_status.get("error"),
                recommended=model_id in ["gpt-4", "claude-4.1", "deepseek-chat"]
            )
            models.append(model)
        
        # 如果没有发现模型但配置了模型名称，添加手动配置的模型
        if not discovered_models and config.get("model_name"):
            health_status = await self.health_checker.check_model_health(
                base_url, api_key, config["model_name"], provider
            )
            
            model = AvailableModel(
                id=f"{provider}_{config['model_name']}",
                name=config["model_name"],
                display_name=config.get("display_name", config["model_name"]),
                provider=provider,
                provider_name=config.get("provider_name", provider.title()),
                base_url=base_url,
                status=health_status.get("status", "unknown"),
                capabilities=ModelCapabilities(),
                last_checked=datetime.now(),
                response_time=health_status.get("response_time"),
                error_message=health_status.get("error")
            )
            models.append(model)
        
        return models

# 创建服务实例
discovery_service = ModelDiscoveryService()

# API路由
@router.get("/available", response_model=ModelDiscoveryResponse)
async def get_available_models(
    force_refresh: bool = Query(False, description="强制刷新缓存"),
    current_user: dict = Depends(get_current_user)
):
    """
    获取所有可用的模型列表
    基于用户配置的API密钥动态检测模型可用性
    """
    try:
        user_id = current_user.get("sub") or current_user.get("user_id")
        models = await discovery_service.get_available_models(force_refresh, user_id)
        return ModelDiscoveryResponse(
            models=models,
            last_refresh=datetime.now(),
            cache_ttl=900
        )
    except Exception as e:
        logger.error(f"Error getting available models: {e}")
        raise HTTPException(status_code=500, detail=str(e))

class ModelDiscoverRequest(BaseModel):
    provider: str = Field(..., description="模型提供商")
    base_url: str = Field(..., description="API基础URL")  
    api_key: str = Field(..., description="API密钥")

@router.post("/discover")
async def discover_models(
    request: ModelDiscoverRequest,
    current_user: dict = Depends(get_current_user)
):
    """
    主动发现特定提供商的模型
    用于测试新的API配置
    """
    try:
        models = []
        if request.provider.lower() == "openai":
            models = await discovery_service.discover_openai_models(request.base_url, request.api_key)
        elif request.provider.lower() in ["anthropic", "claude"]:
            models = await discovery_service.discover_anthropic_models(request.base_url, request.api_key)
        elif request.provider.lower() == "deepseek":
            models = await discovery_service.discover_deepseek_models(request.base_url, request.api_key)
        else:
            raise HTTPException(status_code=400, detail=f"Unsupported provider: {request.provider}")
        
        return {"success": True, "models": models}
    except Exception as e:
        logger.error(f"Error discovering models: {e}")
        return {"success": False, "error": str(e), "models": []}

@router.get("/health/{model_id}")
async def check_model_health(
    model_id: str,
    current_user: dict = Depends(get_current_user)
):
    """
    检查特定模型的健康状态
    """
    try:
        # 从model_id解析provider和实际的model_name
        parts = model_id.split("_", 1)
        if len(parts) != 2:
            raise HTTPException(status_code=400, detail="Invalid model ID format")
        
        provider, model_name = parts
        
        # 获取配置
        configs = await discovery_service.config_manager.get_user_configs()
        config = next((c for c in configs if c.get("provider", "").lower() == provider), None)
        
        if not config:
            raise HTTPException(status_code=404, detail="Model configuration not found")
        
        # 检查健康状态
        health_status = await discovery_service.health_checker.check_model_health(
            config["base_url"],
            config["api_key"],
            model_name,
            provider
        )
        
        return health_status
    except HTTPException:
        raise
    except Exception as e:
        logger.error(f"Error checking model health: {e}")
        raise HTTPException(status_code=500, detail=str(e))

@router.post("/refresh-cache")
async def refresh_model_cache(
    current_user: dict = Depends(get_current_user)
):
    """
    手动刷新模型缓存
    """
    try:
        models = await discovery_service.get_available_models(force_refresh=True)
        return {
            "success": True,
            "message": "Cache refreshed successfully",
            "model_count": len(models)
        }
    except Exception as e:
        logger.error(f"Error refreshing cache: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/test", response_model=Dict[str, Any])
async def test_model_connection_proxy(
    test_request: Dict[str, Any],
    current_user: dict = Depends(get_current_user)
) -> Dict[str, Any]:
    """
    测试模型连接 - 代理到model_config的测试端点
    """
    return await config_test_model_connection(test_request, current_user)